/**************************************************************
 * 
 * Copyright ? 2014，北京福富软件技术股份有限公司
 * All Rights Reserved.
 * ------------------------------------------------------------
 * 文件名称：Elem.java
 * 文件摘要：页面使用的[JSON相关转换]节点类
 * 初始版本：V1.0.0
 * 初始作者：lhong
 * 完成日期：2014-03-01
 * 
 **************************************************************/
package com.util.Json;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**************************************************************************
 * 
 * 类名：Elem<br>
 * <br>
 * 功能：页面使用的[JSON相关转换]节点类<br>
 * <br>
 * 作者：lhong 2014-03-01<br>
 * <br>
 * 属性列表：<br>
 * <br>
 * 方法列表：<br>
 * 		...<br>
 * <br>
 * 修改记录：<br>
 * 		日期				修改人			修改说明<br>		
 * 
 **************************************************************************/
public class Elem {
	
	private Object obj;									//数据对像
	
	private String[] cols;								//需要显示的列
	
	private boolean flag = false;						//是否需要每层都按cols列来进行反射标志
	
	
	/**************************************************************************
	 * 
	 * 函数名：public Elem(Object obj,String... cols)<br>
	 * <br>
	 * 功能：节点的构造方法<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		Object obj			->	数据对像<br>
	 * 		String... cols		->	需要更新的列<br>
	 * <br>
	 * 返回值：<br>
	 * 		无<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * 
	 **************************************************************************/
	public Elem(Object obj,String... cols){
		this.obj = obj;
		this.cols = cols;
	}
	
	/**************************************************************************
	 * 
	 * 函数名：public Elem(Object obj,boolean flag,String... cols)<br>
	 * <br>
	 * 功能：节点的构造方法<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		Object obj			->	数据对像<br>
	 * 		boolean flag		->	是否需要每层都按cols列来进行反射标志<br>
	 * 		String... cols		->	需要更新的列<br>
	 * <br>
	 * 返回值：<br>
	 * 		无<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * 
	 **************************************************************************/
	public Elem(Object obj,boolean flag,String... cols){
		this.obj = obj;
		this.flag = flag;
		this.cols = cols;
	}
	
	
	/**************************************************************************
	 * 
	 * 函数名：	public Object getJSONObjectByElem() 
	 * 		throws SecurityException, IllegalArgumentException,
	 * 		IllegalAccessException, InvocationTargetException, JSONException<br>
	 * <br>
	 * 功能：将Elem对像转换成Json对像<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		无<br>
	 * <br>
	 * 返回值：<br>
	 * 		Object	->	Json对像<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * @throws JSONException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 * 
	 **************************************************************************/
	public Object getJSONObjectByElem() 
			throws SecurityException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException, JSONException{
		return getJSONByObject(this.obj,this.cols);
	}
	
	/**************************************************************************
	 * 
	 * 函数名：private Object getJSONByObject(Object obj,String... cols) 
	 * 		throws SecurityException, IllegalArgumentException,
	 * 		IllegalAccessException, InvocationTargetException, JSONException<br>
	 * <br>
	 * 功能：将object对像转换成Json对像<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		Object obj			->	object对像<br>
	 * 		String... cols		->	需要更新的列<br>
	 * <br>
	 * 返回值：<br>
	 * 		Object	->	Json对像<br><br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * @throws JSONException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 * 
	 **************************************************************************/
	private Object getJSONByObject(Object obj,String... cols) 
			throws SecurityException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException, JSONException{
		if(obj==null)
			return null;
		String type = getTypeByObject(obj);
		if(type.equals("Bean")){
			return getJSONObjectByBean(obj, cols);
		}else if(type.equals("List")){
			return getJSONArrayByList((List)obj, cols);
		}else if(type.equals("Map")){
			return getJSONArrayByMap((Map)obj, cols);
		}
		//如果都不满足，则返回值
		return obj;
	}
	
	
	/**************************************************************************
	 * 
	 * 函数名：	private String getTypeByObject(Object obj)<br>
	 * <br>
	 * 功能：判断object对像的类型<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		Object obj			->	Object对像<br>
	 * <br>
	 * 返回值：<br>
	 * 		String 	->	类型<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * 
	 **************************************************************************/
	private String getTypeByObject(Object obj){
		if(obj instanceof List){
			return "List";
		}else if(obj instanceof Map){
			return "Map";
		}else if(obj instanceof String || obj instanceof Integer || obj instanceof Character || obj instanceof Double ||
				obj instanceof Float || obj instanceof Boolean || obj instanceof Byte || obj instanceof Short || obj instanceof Long){
			return "other";
		}
		return "Bean";
	}
	
	
	
	/**************************************************************************
	 * 
	 * 函数名：	private JSONObject getJSONObjectByBean(Object obj,String... cols) 
	 * 		throws SecurityException, IllegalArgumentException,
	 * 		IllegalAccessException, InvocationTargetException, JSONException<br>
	 * <br>
	 * 功能：将bean对像转换成JSONObject对像<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		Object obj			->	bean对像<br>
	 * 		String... cols		->	需要转换的列<br>
	 * <br>
	 * 返回值：<br>
	 * 		JSONObject	->	Bean转换的JSONObject对像<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * @throws SecurityException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws JSONException 
	 * 
	 **************************************************************************/
	private JSONObject getJSONObjectByBean(Object obj,String... cols) 
			throws SecurityException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException, JSONException{
		//定义返回结果JSONObject
		JSONObject jObject = new JSONObject();
		//得到bean对像的类型 
		 Class c = obj.getClass();
		 //如果传入的属性名称为空,则反射取出该bean的所有属性
		if(cols==null||cols.length==0){
			Field[] fields = c.getDeclaredFields();
			cols = new String[fields.length];
			for (int i = 0; i < fields.length; i++) {
				cols[i] = fields[i].getName();
			}
		} 
		
		//根据属性列表取值并封装JSONObject
		String key,colName;
		Object value;
		for (int i = 0; i < cols.length; i++) {
			//如果需要别名,则传递col时使用#隔开，例:id#UserId(取得属性Id的值,但转成JSONObject时,key为UserId)
			key = cols[i].indexOf("#")>-1?cols[i].split("#")[1]:cols[i];
			colName = cols[i].indexOf("#")>-1?cols[i].split("#")[0]:cols[i];
			//取得该属性的get方法
			Method method;
			try{
				method = c.getMethod("get"+colName.substring(0, 1).toUpperCase() + colName.substring(1));
			}catch (NoSuchMethodException e) {
				//如果没有该属性的get方法路过
				continue;
			}
			//通过反射取得属性的值
			value = method.invoke(obj)==null?"":method.invoke(obj);
			//若是flag = false则只对第一层的自定义列进行反射,flag = true则每层都按自定义列进行反射 
			if(flag)
				value = getJSONByObject(value,cols);
			else
				value = getJSONByObject(value);
			jObject.put(key, value);
		}
		return jObject;
	}
	
	/**************************************************************************
	 * 
	 * 函数名：private JSONArray getJSONArrayByList(List list,String... cols) 
	 * 		throws SecurityException, IllegalArgumentException, IllegalAccessException,
	 * 		InvocationTargetException, JSONException<br>
	 * <br>
	 * 功能：将List对像转换成JSONArray对像<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		List list			->	List对像<br>
	 * 		String... cols		->	需要转换的列<br>
	 * <br>
	 * 返回值：<br>
	 * 		JSONArray	->	List转换的JSONArray对像<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * @throws JSONException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 * 
	 **************************************************************************/
	private JSONArray getJSONArrayByList(List list,String... cols) 
			throws SecurityException, IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, JSONException{
		//定义返回结果JSONArray
		JSONArray jArray = new JSONArray();
		if(list!=null&&!list.isEmpty()){
			for (int i = 0; i < list.size(); i++) {
				Object value = getJSONByObject(list.get(i),cols);
				jArray.put(value);;
			}
		}
		return jArray;
	}
	
	
	
	/**************************************************************************
	 * 
	 * 函数名：private JSONObject getJSONArrayByMap(Object obj,String... cols) 
	 *		throws SecurityException, IllegalArgumentException, IllegalAccessException,
	 *		InvocationTargetException, JSONException<br>
	 * <br>
	 * 功能：将Map对像转换成JSONObject对像<br>
	 * <br>
	 * 作者：lhong 2014-03-01<br>
	 * <br>
	 * 参数表：<br>
	 * 		Map map				->	Map对像<br>
	 * 		String... cols		->	需要转换的列<br>
	 * <br>
	 * 返回值：<br>
	 * 		JSONObject	->	Map转换的JSONObject对像<br>
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * @throws JSONException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 * 
	 **************************************************************************/
	private JSONObject getJSONArrayByMap(Map map,String... cols) 
			throws SecurityException, IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, JSONException{
		//定义返回结果JSONObject
		JSONObject jObject = new JSONObject();
		Set keySet = map.keySet();
		Iterator kit = keySet.iterator();
		while (kit.hasNext()) {
			String key = (String)kit.next();
			Object value = map.get(key);
			value = getJSONByObject(value,cols);
			jObject.put(key,value);
		}
		return jObject;
	}
}
